Skip to main content

第29章 函数

函数是C++程序的基本组成单位,它将一段具有特定功能的代码块封装起来,通过函数名可以被多次调用,从而提高代码的复用性、可读性和可维护性。本章将详细介绍函数的定义、调用、声明、变量作用域及参数传递等核心知识点。

29.1 函数的定义

函数的定义是指创建一个函数,明确其功能、名称、参数和返回值。C++中函数定义的基本语法如下:

返回值类型 函数名(参数列表){
//函数体:实现函数功能的语句块
}

29.1.1 各部分说明

  • 返回值类型:表示函数执行完毕后返回的数据类型,如intdoublevoid(表示无返回值)等
  • 函数名:遵循标识符命名规则,用于标识函数,应体现函数的功能。
  • 参数列表:由零个或多个参数组成,每个参数需指定类型和名称,多个参数之间用逗号分隔,用于接收函数调用时传递的数据。
  • 函数体:用花括号{}包裹的语句块,包含实现函数功能的具体代码。

29.1.2 示例

//定义一个计算两个整数之和的函数
int add(int a,int b){
int sum=a+b;
return sum;//返回计算结果
}

//定义一个无返回值、无参数的函数
void printHello(){
cout << "Hello, Function!" << endl;
}

29.2 函数的参数

函数的参数是函数与外部进行数据交互的接口,位于函数定义的参数列表中,也称为形式参数(简称形参)。

29.2.1 参数的分类

  1. 普通参数:具有具体的类型和名称,用于接收函数调用时传递的具体值。
//计算矩形面积,width和height为普通参数
double calculateArea (double width, double height) {
return width * height;
}
  1. 默认参数:在函数定义时为参数指定默认值,当函数调用时未提供该参数的值,将使用默认值。默认参数必须从右向左定义,且在函数声明和定义中只能指定一次。
//带默认参数的函数,discount默认值为0.9
double calculatePrice (double originalPrice, double discount = 0.9) {
return originalPrice*discount;
}
//调用示例
int main(){
cout << calculatePrice (100) << endl;//使用默认折扣0.9,输出90
cout << calculatePrice (100, 0.8) << endl;//传入折扣0.8,输出80
return 0;
}
  1. 占位参数:只有参数类型,没有参数名称的参数,通常用于函数重载或后续扩展。
//占位参数int,调用时需传递一个int的值
void func(int a, int) {
cout << "a=" << a << endl;
}
int main(){
func(10, 20);//第二个参数20传递给占位参数,输出a=10
return 0;
}

29.3 函数的声明

函数的声明是指告诉编译器函数的名称、返回值类型和参数列表,以便编译器在函数被调用时能够正确检查参数和返回值。函数声明的语法与函数定义的原型部分相同,末尾加分号。

29.3.1 声明的作用

当函数定义在调用之后时,必须先声明函数,否则编译器会报错。函数声明可以放在函数调用之前,通常放在头文件中或源文件的开头。

29.3.2 示例

//函数声明
int max(int x, int y);
int main(){
int a=10,b=20;
cout << max(a,b)<<endl;//调用函数,编译器已知max信息
return 0;
}
//函数定义(在调用之后)
int max(int x,int y){
return x>y?x:y;
}

29.4 变量的作用域

变量的作用域是指变量在程序中能够被访问的有效范围,根据作用域的不同,变量可分为局部变量和全局变量。

29.4.1 局部变量

在函数内部或代码块(如iffor语句块)中定义的变量,其作用域仅限于定义它的函数或代码块内部。

void func(){
int a=10;//局部变量,仅func内可用
if(a>5){
int b=20;//局部变量,仅if块内可用
cout<<a+b<<endl;//合法
}
//cout<<b<<endl;//非法,b作用域已结束
}

29.4.2 全局变量

在所有函数外部定义的变量,作用域是从定义位置开始到整个程序结束,所有函数均可访问。

int globalVar=100;//全局变量
void func1(){
cout<<globalVar<<endl;//可读取
}
void func2(){
globalVar= 200;//可修改
cout << globalVar << endl;
}
int main(){
func1();//输出100
func2();//输出200
cout<<globalVar<<endl;//输出200
return 0;
}

29.4.3 注意事项

  1. 局部变量与全局变量同名时,局部变量会屏蔽同名校全局变量;
  2. 尽量少用全局变量,容易出现意外修改,降低代码可维护性。

29.5 函数的调用

函数调用是指使用已定义的函数执行功能,调用时传入实际参数(实参)。 调用格式:函数名(实参列表);

29.5.2 示例

int add(int a,int b){
return a +b;
}
void printInfo(string name, int age) {
cout<<"姓名:"<<name<<",年龄:"<<age<<endl;
}
int main(){
int sum=add(3,5);//实参3、5,接收返回值
cout<<"和为:"<<sum<<endl;//输出8
printInfo("张三",20);//无返回值调用
return 0;
}

29.6 函数的嵌套调用与递归调用

29.6.1 嵌套调用

一个函数内部调用另一个函数,称为嵌套调用。

int add(int a,int b){
return a +b;
}
int multiply(int a, int b){
return a*b;
}
int calculate (int x, int y) {
int sum=add(x,y);//嵌套调用加法
int product=multiply(x,y);//嵌套调用乘法
return sum + product;
}
int main(){
cout << calculate(2, 3)<<endl; // 2+3 + 2*3 = 11
return 0;
}

29.6.2 递归调用

函数直接或间接调用自身,称为递归调用。递归必须满足两点:

  1. 存在递归终止条件;
  2. 每次调用问题规模缩小。

示例(阶乘):

int factorial(int n) {
if(n==0||n==1){//终止条件
return 1;
} else {
return n*factorial(n);//递归调用,规模减小
}
}
int main(){
cout << factorial(5) << endl;//5! = 120
return 0;
}